home *** CD-ROM | disk | FTP | other *** search
-
- Just when you thought it was safe to turn your monitor rightside-up...
-
- Here are the sources and uuencoded binary to a new version of my
- silly upside down desk accessory. This one refreshes the screen at
- more than 10 Hz when there is little change between refreshes.
-
- It keeps checksums on 32 byte blocks of the screen and reverses the
- changed blocks.
-
- I promise not to post any more of these. Honest.
-
- What do you mean, pointless?
-
- Jan Gray
-
-
- ud.c:
- ------------------
- /*
- * Upside-down DA, v.2 ...a somewhat less disappointing experiment
- *
- * Jan Gray 1986
- *
- * link: accstart,ud,flip,aesbind,osbind
- */
-
- #include "gemdefs.h"
- #include "osbind.h"
-
- #define NULL 0
- #define SCR_BYTES 32000L
- #define SCR_ALIGN 512L /* must page align screen */
- #define Supexec(code) xbios(38, code)
-
- typedef unsigned char Byte; /* must be unsigned! */
-
- long Chksums[32000/32];
- Byte RevBytes[256];
-
- Byte *RealScreen; /* real screen address */
- Byte *FlipScreen; /* flipped screen address */
- Byte *Phys; /* passed to setPhysBase() */
-
- setPhysBase();
-
- main()
- {
- extern int gl_apid;
- char menuName[20];
- int menuID;
- int event;
- int msg[8];
- int ret;
-
- appl_init();
-
- buildRevBytes();
- zapChksums();
-
- RealScreen = Physbase();
- FlipScreen = (Byte *)((Malloc(SCR_BYTES + SCR_ALIGN) + (SCR_ALIGN-1))
- & ~(SCR_ALIGN-1));
-
- menuName[0] = NULL;
- menuID = menu_register(gl_apid, menuName);
-
- for (;;) {
- /* Wait for accessory open message */
- strcpy(menuName, " Upside-down");
- do {
- event = evnt_mesag(msg);
- } while (!(msg[0] == AC_OPEN && msg[4] == menuID));
-
- /* Flip screen */
- refreshFlip();
- Phys = FlipScreen;
- Supexec(setPhysBase);
-
- /*
- * Wait for accessory open or close message or 50 ms timeout.
- */
- strcpy(menuName, " Rightside-up");
- do {
- event = evnt_multi(MU_MESAG | MU_TIMER,
- 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- msg, 50, 0,
- &ret, &ret, &ret, &ret, &ret, &ret);
- if (event & MU_TIMER)
- refreshFlip(); /* 20 to 150 ms */
- } while (!((event & MU_MESAG) &&
- (msg[0] == AC_OPEN && msg[4] == menuID ||
- msg[0] == AC_CLOSE && msg[3] == menuID)));
-
- /* Restore screen */
- Phys = RealScreen;
- Supexec(setPhysBase);
- }
- }
-
- buildRevBytes() /* Build the byte reversal table */
- {
- register int i;
-
- for (i = 0; i < 256; i++)
- RevBytes[i] = ((i & 1) << 7) | ((i & 2) << 5) |
- ((i & 4) << 3) | ((i & 8) << 1) |
- ((i & 0x10) >> 1) | ((i & 0x20) >> 3) |
- ((i & 0x40) >> 5) | ((i & 0x80) >> 7);
- }
-
- zapChksums() /* Initialize the checksums to ff's */
- {
- register long *p;
- register long ffffffff = 0xffffffffL;
-
- for (p = Chksums; p < &Chksums[32000/32]; ) {
- *p++ = ffffffff;
- *p++ = ffffffff;
- *p++ = ffffffff;
- *p++ = ffffffff;
- }
- }
-
- #define VBASE_HIGH (Byte *)0xff8201L
- #define VBASE_LOW (Byte *)0xff8203L
- /*
- * setPhysBase -- set the physical screen to Phys. I don't use Setscreen()
- * because it seems to clear the old logical screen...I don't want the
- * ST to know that anything funny is going on, just to go merrily on its
- * way writing to what it thinks is the physical screen...
- */
- setPhysBase()
- {
- *VBASE_HIGH = (Byte)((unsigned long)Phys >> 16);
- *VBASE_LOW = (Byte)((unsigned long)Phys >> 8);
- }
-
- /* Writing strcpy here saves us from linking with gemlib */
- strcpy(dst, src)
- register char *dst;
- register char *src;
- {
- while (*dst++ = *src++)
- ;
- }
- ----------------------
- flip.s:
- ----------------------
- *
- * flip.s
- *
- * Assembler _refreshFlip.
- *
- * Reverse the real screen onto the flip screen. Rather than reversing
- * every byte every time called (which is slow -- about 120 ms per call),
- * we reverse only those bytes which have changed since the last call.
- *
- * Instead of saving yet another copy of the screen, we keep a longword
- * checksum for each block of 32 bytes. If a new checksum differs, we save
- * it away and reverse that 32 byte block.
- *
- * Since the screen changes little between calls, this is a big win, reducing
- * the average time spent here from about 120 to 20 ms per call.
- *
- *
- * Registers used
- * a5 - real screen
- * a4 - flip screen start
- * a3 - flip screen
- * a2 - reverse table
- * a1 - checksum table
- * a0 - constant 32
- * d7-d0 - scratch
- .globl _RealScreen
- .globl _FlipScreen
- .globl _RevBytes
- .globl _Chksums
- .text
- .globl _refreshFlip
- _refreshFlip:
- link a6,#0
- movem.l d0-d7/a0-a5,-(sp)
- move.l _RealScreen,a5
- move.l _FlipScreen,a4
- move.l a4,a3
- add.l #32000,a3 * a3 = end of FlipScreen
- move.l #_RevBytes,a2
- move.l #_Chksums,a1
- move.l #32,a0
- loop:
- movem.l (a5)+,d0-d7 * fetch 32 bytes
- add.l d1,d0 * compute new checksum
- add.l d2,d0
- add.l d3,d0
- add.l d4,d0
- add.l d5,d0
- add.l d6,d0
- add.l d7,d0
- cmp.l (a1)+,d0 * compare against old checksum
- bne rev * reverse line if different
- sub.l a0,a3 * skip 32 bytes on flip screen
- loop1:
- cmp.l a4,a3 * done?
- bcc loop
- movem.l (sp)+,d0-d7/a0-a5
- unlk a6
- rts
-
- rev:
- move.l d0,-4(a1) * differs; save new checksum
- sub.l a0,a5 * adjust a5 to front of 32 bytes
- moveq.l #0,d0 * load upper byte with 0
- move.b (a5)+,d0 * copy real byte through byte-
- move.b 0(a2,d0.w),-(a3) * reversal table to flip screen
- move.b (a5)+,d0 * likewise for 31 bytes
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- move.b (a5)+,d0
- move.b 0(a2,d0.w),-(a3)
- bra loop1 * continue
- O.SNG to Àע: /ÇSTPAT.PRG ⇩¬♪t O SUNNING.TNY